"""
RMSProp

RMSProp算法与AdaGrad算法非常相似，因为两者都使用了梯度的平方来缩放系数
RMSProp算法与动量法都使用泄漏平均值。但是，RMSProp算法使用该技术来调整按系数顺序的预处
理器。

实验中，我们需要自己调整学习率
系数gamma决定了在调整每个坐标比例时历史记录的时长
"""
import math

import numpy as np
import matplotlib.pyplot as plt

w1 = np.linspace(-1, 1, 30)
w2 = np.linspace(-0.8, 0.8, 30)
e = 0.1 * w1 ** 2 + 2 * w2 ** 2

current_w1 = -1
current_w2 = -0.8

lr = 0.2
num_epochs = 10
predict_w = []

# 泄漏平均值参数: 数值越大衰减越缓慢
gamma = 0.9
# 防零小偏置项
eps = 1e-6
# 累加梯度
s1 = 0
s2 = 0

for i in range(num_epochs):
    predict_w.append([current_w1, current_w2])
    slope1 = 0.2 * current_w1
    slope2 = 4 * current_w2
    s1 = gamma * s1 + (1 - gamma) * slope1 ** 2
    s2 = gamma * s2 + (1 - gamma) * slope2 ** 2
    current_w1 -= lr / math.sqrt(s1 + eps) * slope1
    current_w2 -= lr / math.sqrt(s2 + eps) * slope2

predict_w = np.array(predict_w)
x1, x2 = np.meshgrid(w1, w2, indexing='ij')
plt.contour(x1, x2, x1 ** 2 + 2 * x2 ** 2, colors="#1f77b4")
plt.plot(predict_w[:, 0], predict_w[:, 1], 'ro-')
plt.show()
